본문으로 건너뛰기

Thread

스레드는 프로세스 내에서 실행되는 여러 흐름의 단위이다. 스레드마다 다른 실행 흐름을 가지기 때문에 각자 레지스터 집합과 스택 영역을 가지며 힙 영역은 공유된다. 여러 스레드가 동시에 실행하는 방법은 I/O 작업과 같이 시간이 오래 걸리는 작업 중에 CPU 사용이 많은 작업을 하고 싶을 때와 같은 상황에 유용하게 쓰일 수 있다. 또한, 서버 프로그램과 같이 워커(Worker)가 여럿 필요한 경우에도 유용하다. 만약 멀티 프로세서 환경에서 어떤 작업들이 서로 의존성이 없다면 동시에 실행함으로써 속도를 향상할 수 있다. 스레드는 실행 흐름은 독립적이지만 메모리 공간은 공유하고 있기 때문에 경량 프로세스(Light Weight Process)라고 부르기도 한다.

기본적으로 프로세스당 최소 1개의 스레드를 가지고 있고 그것을 메인 스레드라고 한다.

멀티 스레드

멀티 스레딩을 지원하는 방법으로는 다대일, 일대일, 다대다 방법이 있다. 일반적으로 사용자가 생성하는 스레드는 유저 수준 스레드라고 분류하고 실제 시스템에서 실행되는 스레드를 커널 수준 스레드라고 하는데, 유저 수준 스레드와 커널 수준 스레드를 어떤 방식으로 맵핑하느냐의 차이다. 다대일 모델은 여러 유저 수준 스레드를 하나의 커널 수준 스레드에 사상하고, 일대일 모델은 유저 수준 스레드마다 커널 수준 스레드에 사상한다. 다대다 모델은 여러 유저 수준 스레드를 여러 커널 수준 쓰레드에 사상한다. 한 유저 수준 스레드에서 Blocking 연산을 하는 경우 다른 모든 유저 스레드가 멈춘다는 점에서 다대일 모델은 통용되기 어렵다. 커널 수준 스레드는 생성하기에 오버헤드가 있으므로 일대일 모델보다는 현실적으로 다대다 모델이 사용된다.

하나의 응용 프로그램에서 여러 스레드를 구성해 각 스레드가 하나의 작업을 처리하는 것

스레드들이 공유 메모리를 통해 다수의 작업을 동시에 처리할 수 있도록 해준다.

장점: 독립적인 프로세스에 비해 공유 메모리만큼의 시간, 자원 손실이 감소 전역 변수와 정적 변수에 대한 자료 공유 가능

단점: 안정성 문제. 하나의 스레드가 데이터 공간 망가뜨리면, 모든 스레드가 작동 불능 상태(공유 메모리를 갖기 때문)

멀티 스레드의 안정성에 대한 단점은 Critical Section 기법을 통해 대비한다.

하나의 스레드가 공유 데이터 값을 변경하는 시점에 다른 스레드가 그 값을 읽으려할 때 발생하는 문제를 해결하기 위한 동기화 과정

상호배제, 진행, 한정된 대기를 충족해야함

멀티 프로세스 대신 멀티 스레드를 사용하는 이유?

  • 프로그램을 여러개 키는 것보다 하나의 프로그램 안에서 여러 작업을 해결하는 것이다.

자원의 효율성 증대

  • 멀티 프로세스로 실행되는 작업을 멀티 스레드로 실행할 경우, 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있다.
  • 스레드는 프로세스 간의 Context Switching시 단순히 CPU 레지스터 교체 뿐만 아니라 RAM과 CPU 사이의 캐쉬 메모리에 대한 데이터까지 초기화되므로 오버헤드가 크기 때문
  • 스레드는 프로세스 내의 메모리를 공유하기 때문에 독립적인 프로세스와 달리 스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다.

처리 비용 감소 및 응답 시간 단축

  • 프로세스 간의 통신(IPC) 보다 스레드 간의 통신의 비용이 적으므로 작업들 간의 통신의 부담이 줄어든다.
  • 스레드는 스택 영역을 제외한 모든 메모리의 영역을 공유한다.
  • Context Switching시 스레드는 Stack 영역만 처리하기 때문에 프로세스보다 전환의 속도가 빠르다.

멀티 스레딩의 장점

프로세스를 이용하여 동시에 처리하던 일을 스레드로 구현할 경우 메모리 공간과 시스템 자원 소모가 줄어든다. 스레드 간의 통신이 필요한 경우에도 별도의 자원을 이용하는 것이 아니라 전역 변수의 공간 또는 동적으로 할당된 공간인 Heap 영역을 이용하여 데이터를 주고받을 수 있다. 그렇기 때문에 프로세스 간 통식 방법에 비해 스레드 간의 통신 방법이 훨씬 간단하다. 심지어 스레드의 Context Switching는 프로세스의 Context Switching와는 달리 캐시 메모리를 비울 필요가 없기 때문에 더 빠르다. 따라서 자원 소모가 자연스럽게 프로그램의 응답 시간이 단축된다.

멀티 스레딩의 단점

멀티 프로세스 기반으로 프로그래밍을 할 때는 프로세스 간 공유하는 자원이 없기 때문에 동일한 자원에 동시에 접근하는 일이 없었지만 멀티 스레딩을 기반으로 프로그래밍할 때는 이 부분을 신경써줘야 한다. 서로 다른 스레드가 데이터와 힙 영역을 공유하기 때문에 어떤 스레드가 다른 스레드에서 사용중인 변수나 자료구조에 접근하여 엉뚱한 값을 읽어오거나 수정할 수 있다. 그렇기 때문에 멀티 스레딩 환경에서는 동기화 작업이 필요하다. 동기화를 통해 작업 처리 순서를 컨트롤 하고 공유 자원에 대한 접근을 컨트롤 하는 것이다. 하지만 이로 인해 병목 현상이 발생하여 성능이 저하될 가능성이 높다. 그러므로 과도한 락으로 인한 병목 현상을 줄여야 한다.

멀티 스레드 vs 멀티 프로세스


멀티 스레드는 멀티 프로세스보다 적은 메모리 공간을 차지하고 문맥 전환이 빠르다는 장점이 있지만, 오류로 인해 하나의 스레드가 종료되면 전체 스레드가 종료될 수 있다는 점과 동기화 문제를 안고 있다. 반면 멀티 프로세스 방식은 하나의 프로세스가 죽더라도 다른 프로세스가 영향을 끼치지 않고 정상적으로 수행된다는 장점이 있지만, 멀티 스레드보다 많은 메모리 공간과 CPU 시간을 차지한다는 단점이 존재한다.

User Thread

  • 유저 영역의 라이브러리로 구현된 스레드
  • 커널은 프로세스 내 유저 스레드를 알지 못한다.
  • 커널은 프로세스 단위로 자원을 할당하기 때문에, 스레드 Block => 프로세스 Block => 프로세스 내 다른 스레드도 Block

Kernel Thread

  • 운영체제가 직접 관리하는 스레드
  • 논리적 코어와 매핑되는, 시스템의 실제 스레드
  • 커널 영역에서 스레드의 생성, 관리 수행
  • 커널이 각 스레드를 개별적으로 관리
    • 프로세스 내 스레드들이 병렬 수행 가능
    • 하나의 스레드가 Block 되어도 다른 스레드는 계속 작업 가능

Multi Threading Model

  • 다대일 모델: User Thread 여러 개가 하나의 Kernel Thread에 매핑된다. 스레드 관리가 유저 영역의 라이브러리에 의해 수행되므로 효율적이지만, 한 User Thread가 Block되면 Kernel Thread 자체가 Block된다. 또한, 한번에 하나의 User Thread만 Kernel에 엑세스 할 수 있으므로 여러 스레드로 병렬 실행할 수 없다.
  • 일대일 모델: User Thread 하나당 Kernel Thread 하나씩 매핑된다. 프로세스 내 스레드가 병렬 실행이 가능하다는 장점이 있고, 다대일 모델의 많은 문제가 해결되지만, 큰 overhead가 발생할 수 있다.
  • 다대다 모델: User Thread를 동일한 수, 혹은 그 이하의 Kernel Thread에 매핑하여, 이전 두 모델의 단점을 극복. User Thread가 Block되어 연결된 Kernel Thread가 Block되어도 다른 User Thread를 다른 Kernel Thread로 매핑하여 대기 상태에 빠지는 것을 해결할 수 있다.

Reference